Class 2 – 10/29/2002
Perl Variables (review and examples)
Scalars
A scalar is the simplest type of variable. It holds a single value,
which can be a string or a number. Internally, Perl stores scalars as
strings, which means that it is not terribly well-suited for
number-crunching, since it has to keep converting strings to numbers
and back all the time.
To assign a value to a scalar:
my $animal = "camel";
my $answer = 42;
Scalar values can be
strings, integers or floating point numbers, and Perl will
automatically convert between them as required. There is no need to
pre-declare your variable types.
You can also assign
several scalars at once:
($a, $b, $c) = (1, 2, 3);
($a, $b, $c) = ($c, $b, $a + ($b * $a));
The second line
illustrates that values on the right are determined before the
assignments happen on the left, so you can use this to swap two
variables without a temporary.
Scalar values can be used
in various ways:
print $animal;
print "The animal is $animal\n";
print "The square of $answer is ", $answer * $answer, "\n";
There are a number of
"magic" scalars with names that look like punctuation or
line noise. These special variables are used for all kinds of
purposes, and a handout with these will be passed around. The only
one you need to know about for now is $_ which is the "default
variable". It's used as the default argument to a number of
functions in Perl, and it's set implicitly by certain looping
constructs.
Arrays
Arrays
are ordered lists of values. The name ``array'' is traditional,
although they're more akin to linked lists or deques. Use an array
any time you need a list of things
To
assign values to an array:
my @animals = ("camel", "llama", "owl");
my @numbers = (23, 42, 69);
my @mixed = ("camel", 42, 1.23);
@array = @otherarray;
@empty = ();
Arrays are zero-indexed.
Here's how you get at elements in an array:
print $animals[0]; # prints "camel"
print $animals[1]; # prints "llama"
Some more advancedexamples:
$foo = $array[9];
$array[3] = $bar;
@other = @array[2,0,1];
@baz = @array[4..8];
($a, $b, @rest) = @array;
You can subscript
anything that has an array value, e.g., literal arrays:
$foo = ("a", "b", "c")[1];
Using @array where Perl
expects to find a scalar value ("in scalar context") will
give you the number of elements in the array:
if (@animals < 5) { ... }
You can do various useful
things to lists:
my @sorted = sort @animals;
my @backwards = reverse @numbers;
Here are some useful
functions for using on arrays:
## Appends value to the end of array.
push(@array, value, ... );
## Pops the last value off of the end of array
## (shortening it by one), and returns it.
$valus = pop(@array);
## Removes the first element from the beginning
## of array (shortening it by one) and returns it.
$value = shift(@array);
## Prepends value to the beginning of array.
$value = unshift(@array, value, ...);
There are a couple of
special arrays too, such as @ARGV (the command line arguments to your
script) and @_ (the arguments passed to a subroutine).
Hashes
The third basic type in
Perl is the hash table, also known as an associative array or hash.
Like arrays, a hash is a collection of values. However, whereas array
indices are integers, hash indices can be any string. You can think
of arrays as being lists, and hashes as being look-up tables.
Hashes have no particular internal order.
To assign values to a
hash:
my %fruit_color = ("apple", "red", "banana", "yellow");
## Or the more normal way:
my %fruit_color = (
apple => "red",
banana => "yellow",
);
## The “=>” operator is much like a comma, but more visually appealing.
## To empty a hash:
%hash = ();
To get at hash elements:
$fruit_color{"apple"}; # gives "red"
You can get at lists of
keys and values with keys() and values().
my @fruits = keys(%fruit_colors);
my @colors = values(%fruit_colors);
To remove a hash entry,
use delete:
delete($fruit_color{"apple"});
Just like special scalars
and arrays, there are also special hashes. The most well known of
these is %ENV which contains environment variables.
Conditional
and Looping Constructs
Perl
has most of the usual conditional and looping constructs except for
case/switch. The conditions can be any Perl expression. In the next
section we will cover the list of operators commonly used for
comparison.
if
if ( condition ) {
...
} elsif ( other condition ) {
...
} else {
...
}
There's also a negated
version of it:
unless ( condition ) {
...
}
This is provided as a
more readable version of: if (!condition).
Note that the braces are
required in Perl, even if you've only got one line in the block.
However, there is a clever way of making your one-line conditional
blocks more English like:
## the traditional way
if ($zippy) {
print "Yow!";
}
## the Perlish post-condition way
print "Yow!" if $zippy;
print "We have no bananas" unless $bananas;
while
while ( condition ) {
...
}
There's also a negated
version, for the same reason we have unless:
until ( condition ) {
...
}
You can also use while in
a post-condition:
print "LA LA LA\n" while 1; # loops forever
The do statement can also
be used with while and until:
do { ... } while ( condition );
do { ... } until ( condition );
for
Exactly
like C:
for (my $i=0; $i <= $max; $i++) {
...
}
foreach
foreach (@array) {
print "This element is $_\n";
}
# You don't have to use the default $_ either...
foreach my $key (keys %hash) {
print "The value of $key is $hash{$key}\n";
}
Perl's
post-condition way can be used with most conditional constructs:
statement if EXPR;
statement unless EXPR;
statement while EXPR;
statement until EXPR;
Builtin
Operators and Functions
Truth
and other booleans
Actually, it's easier to define
what is false: empty arrays and hashes, and nonexistent variables,
are false. For scalars, 0 is false, as is the empty string.
Actually, there are two varieties of empty string: the first is "",
the second is the undefined value.
The undefined value is what you
get if, say, you try to get a hash element that doesn't exist. It is
similar to the NULL pointer in C. You can find out whether a variable
has the undefined value by calling defined($variable) (or
!defined($variable), as the case may be).
You can explicitly set a
variable to the undefined value by using undef:
$var = undef;
That's it for falsehood.
Anything that isn't false is true.
Arithmetic
+ addition
- subtraction
* multiplication
/ division
Numeric comparison
== equality
!= inequality
< less than
> greater than
<= less than or equal
>= greater than or equal
String comparison
eq equality
ne inequality
lt less than
gt greater than
le less than or equal
ge greater than or equal
cmp The generalized string comparison operator.
$a cmp $b returns -1 if $a is less than $b, 1 if $a is greater than $b, and 0 if they are equal.
(Why do we have separate
numeric and string comparisons? Because we don't have special
variable types, and Perl needs to know whether to sort numerically
(where 99 is less than 100) or alphabetically (where 100 comes before
99).
Boolean logic
&& and
|| or
! not
(and, or and not aren't
just in the above table as descriptions of the operators -- they're
also supported as operators in their own right. They're more readable
than the C-style operators, but have different precedence to &&
and friends.)
Miscellaneous
= assignment
. string concatenation
x string multiplication
.. range operator (creates a list of numbers)
Many
operators can be combined with a = as follows:
$a += 1; # same as $a = $a + 1
$a -= 1; # same as $a = $a - 1
$a .= "\n"; # same as $a = $a . "\n";
$a <=> $b; # much like cmp above
Loop-control commands
There are times when you
don't want to finish executing the body of the loop you're in. For
these cases, Perl provides not one, not two, but three special
commands:
Last
This is similar to C's
break statement: it exits the loop immediately (without passing
through the continue block, if any), causing control to continue with
the next statement after the closing brace.
Next
This is similar to C's
continue statement: control passes through the continue block, if
any, then back up to the condition at the top of the loop.
Redo
This has no equivalent in
C. It causes control to go back to the top of the while block, to the
first statement after the opening brace. The continue block is not
executed, and the condition is not evaluated.
Homework
Write
four perl scripts, one for each of the looping constructs mentioned
above (if, while, for, foreach). Each script should use a different
method of comparison. For example if the “if” script
tests numeric values than the “while” script should
compare something different like null/not-null or array size. Use
of other functions and things talked about encouraged.